<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>照片墙效果</title>
<style type="text/css">
*{ margin: 0; padding: 0; }
#ul1{ position: relative; width: 660px; }
#ul1 li{ float: left; list-style: none; width: 200px; height: 150px; margin: 10px; z-index: 1; }
.active{ border: 1px dashed red; }
</style>
<script type="text/javascript" src="move.js"></script>
</head>
<body>
<ul id="ul1">
	<li><img src="images/1.jpg" /></li>
	<li><img src="images/2.jpg" /></li>
	<li><img src="images/3.jpg" /></li>
	<li><img src="images/4.jpg" /></li>
	<li><img src="images/5.jpg" /></li>
	<li><img src="images/1.jpg" /></li>
	<li><img src="images/2.jpg" /></li>
	<li><img src="images/3.jpg" /></li>
	<li><img src="images/4.jpg" /></li>
	<li><img src="images/5.jpg" /></li>
</ul>

<script type="text/javascript">
	/** 涉及到的功能点：
	  * 1、布局转换
	  * 2、拖拽
	  * 3、碰撞检测
	  * 4、查找最小值和出现的位置
	  */
	let iZindex = 2;
	let oPos = []
	let oUl = document.querySelector("#ul1");
	aLi = oUl.querySelectorAll("li")

	// 1. 布局转换
	for(let i = 0; i < aLi.length; i++) {
		aLi[i].index = i;
		oPos.push({ left: aLi[i].offsetLeft, top: aLi[i].offsetTop })
	}
	for(let i = 0; i < aLi.length; i++) {
		aLi[i].style.position = 'absolute';
		aLi[i].style.left = oPos[i].left + "px";
		aLi[i].style.top = oPos[i].top + "px";
		aLi[i].style.margin = '0';
	}

	// 2. 拖拽
	for(let i = 0; i < aLi.length; i++) {
		drag(aLi[i])
	}
	// 封装拖拽功能：
	function drag(obj) {
		obj.onmousedown = function(ev) {
			obj.style.zIndex = iZindex++;  // 解决图片层次问题；

			let disX = ev.clientX - obj.offsetLeft;
			let disY = ev.clientY - obj.offsetTop;

			document.onmousemove = function(ev) {
				obj.style.left = ev.clientX - disX + 'px';
				obj.style.top = ev.clientY - disY + 'px';

				for(let i = 0; i < aLi.length; i++) {
					aLi[i].className = ""

					if(findTarget(obj)) {
						findTarget(obj).className = 'active'
					}	
				}
			}

			document.onmouseup = function() {
				document.onmousemove = null;
				document.onmouseup = null;

				let target = findTarget(obj)
				if(target) {
					target.className = ''
					
					target.style.zIndex = iZindex++
					obj.style.zIndex = iZindex++
					
					// 碰撞上则交互位置
					startMove(obj, oPos[target.index])
					startMove(target, oPos[obj.index])

					// 交换完位置后更新互换后图片新的位置index值
					let temp = obj.index;
					obj.index = target.index;
					target.index = temp;

				} else {
					// 没碰撞上则回到原来的位置
					startMove(obj, oPos[obj.index])
				}
			}

			clearInterval(obj.timer);

			return false;
		}
	}

	// 3. 碰撞检测
	function testCollision(obj1, obj2) {
		/** 如何检测2个物体是否碰上了:
		  * 1. obj1底部在obj2顶部的上方; 上
		  * 2. obj1左边在obj2右边的右方; 右
		  * 3. obj1顶部再obj2底部的下方; 下
		  * 4. obj1右边在obj2左边的左方. 左
		  */
		let [l1,r1,t1,b1] = [obj1.offsetLeft, obj1.offsetLeft + obj1.offsetWidth, obj1.offsetTop, obj1.offsetTop + obj1.offsetHeight]
		let [l2,r2,t2,b2] = [obj2.offsetLeft, obj2.offsetLeft + obj2.offsetWidth, obj2.offsetTop, obj2.offsetTop + obj2.offsetHeight]
		if(b1 < t2 || l1 > r2 || t1 > b2 || r1 < l2) {
			return false
		} else {
			return true
		}
	}

	// 4. 查找碰撞上且距离最近的物体(查找最小值和出现的位置)
	function findTarget(obj) {
		let iMinDis = 999;
		let iMinIndex = -1;

		for(let i = 0; i < aLi.length; i++) {
			if(obj == aLi[i]) continue

			if(testCollision(obj, aLi[i])) {
				let disX = obj.offsetLeft - aLi[i].offsetLeft;
				let disY = obj.offsetTop - aLi[i].offsetTop;
				let distance = Math.sqrt(disX * disX + disY * disY)
				if(distance < iMinDis) {
					iMinDis = distance;
					iMinIndex = i
				}
			}
		}

		if(iMinIndex == -1) {
			return null
		} else {
			return aLi[iMinIndex]
		}
	}
	
</script>
</body>
</html>